/**
 * Namespace responsável pela manipulação de eventos. Adaptado a partir de: 
 * [[http://www.quirksmode.org/blog/archives/2005/10/_and_the_winner_1.html|Quirksmode]].
 *  
 * @name jProton.event
 * @namespace
 */
/**#@+ @extends event */
jProton.event = function(){
  
  /**
   * Lista de eventos registrados
   * @private
   * @memberOf jProton.event
   * @type Object[]
   */
  var _events = new Array();
  var addEventListener = typeof document.addEventListener != 'undefined';
  var attachEvent = typeof document.attachEvent != 'undefined';
  
  return /** @lends jProton.event */ {
    version: 'jProton.event.0.3.9a',
  
    /**
     * Adiciona o tratamento de um evento a um elemento.
     * 
     * @param {Element}  e     Elemento alvo.
     * @param {String}   type  Tipo de evento a ser adicionado.
     * @param {Function} fn    Função de tratamento do evento.   
     */
    add: function(e, type, fn){
      _events.push({e: e, type: type, fn: fn});
  
      if (addEventListener)
        e.addEventListener(type, fn, false)

      else if (attachEvent) {
        e['e'+type+fn] = fn;
        e[type+fn] = function() { e['e'+type+fn](window.event); }
        e.attachEvent('on'+type, e[type+fn]);
      }
    },
  
    /**
     * Remove o tratamento de um evento de um elemento.
     * 
     * @param {Element}  e     Elemento alvo.
     * @param {String}   type  Tipo de evento a ser removido.
     * @param {Function} fn    Função de tratamento do evento.   
     */
    remove: function(e, type, fn){
      var l, fs = fn.toString();

      // Remove o evento da lista de eventos
      for (var i=0,li; li=_events[i]; i++)
        if (li.e==e && li.type==type && (li.fn==fn || li.fn.toString()==fs) ) {
          l = _events.splice(i,1)[0];
          break;
        }

      if (l) {
        // tenha certeza que esta apontado para a função original
        fn = l.fn;
        if (addEventListener)
          e.removeEventListener(type, fn, false)

        else if (attachEvent) {
          e.detachEvent('on'+type, e[type+fn]);
          e[type+fn] = null;
          e['e'+type+fn] = null;
        }
      }
    },
  
    /**
     * Remove todos os eventos adicionados.
     */     
    removeAll: function() {
      for (var i=0; li=_events[i]; i++)
        this.remove(li.e, li.type, li.fn);
    }
  }

  /**#@-*/
}();
